package com.fdb.efp.console.api.rest;

import com.alibaba.fastjson.JSON;
import com.fdb.basic.framework.core.constant.ApplicationConstance;
import com.fdb.basic.framework.core.constant.BaseConstant;
import com.fdb.basic.framework.core.constant.ResponseData;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.core.vo.EngineHttpRequestVO;
import com.fdb.basic.framework.web.util.HttpClientUtil;
import com.fdb.efp.console.service.facade.SequenceService;
import com.fdb.efp.console.common.ConsoleConstant;
import com.fdb.efp.console.service.facade.PubSysInfoService;
import com.fdb.efp.console.common.constance.FlowConstance;
import com.fdb.efp.console.executor.util.AbstractController;
import com.fdb.efp.console.service.FlowCommonService;
import com.fdb.efp.console.service.facade.FlowUrlConfigService;
import com.fdb.efp.console.common.ExcelException;
import com.fdb.efp.console.common.RiskColltConstant;
import com.fdb.efp.console.common.util.ExcelImportRiskmUtil;
import com.fdb.efp.console.service.facade.ColltDelayCaseAppService;
import com.fdb.efp.console.service.facade.ColltDelayCaseRecordService;
import com.fdb.efp.console.service.facade.ColltTaskInfoService;
import com.fdb.efp.console.service.vo.ColltDelayCaseAppVO;
import com.fdb.efp.console.service.vo.ColltDelayCaseRecordVO;
import com.fdb.efp.console.service.vo.ColltTaskInfoVO;
import com.fdb.efp.console.service.vo.excelVo.ColltDelayCaseExcelVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 委外延案申请流程处理类
 */
@RestController
@RequestMapping("/api")
public class ColltDelayCaseApprController extends AbstractController {

    @Autowired
    @Qualifier("colltDelayCaseRecordService")
    private ColltDelayCaseRecordService colltDelayCaseRecordService;

    @Autowired
    @Qualifier("colltDelayCaseAppService")
    private ColltDelayCaseAppService colltDelayCaseAppService;

    @Autowired
    @Qualifier("dbSeqService")
    private SequenceService sequenceService;

    @Autowired
    @Qualifier("flowUrlConfigService")
    private FlowUrlConfigService flowUrlConfigService;

    @Autowired
    @Qualifier("pubSysInfoService")
    private PubSysInfoService pubSysInfoService;

    @Autowired
    @Qualifier("colltTaskInfoService")
    private ColltTaskInfoService colltTaskInfoService;

    @Autowired
    private FlowCommonService flowCommonService;

    private static final String CONTENTTYPE = "application/json;charset=UTF-8";

    private static final String SHEETNAME = "Sheet1";


    /**
     * 单笔延案申请
     * <p>
     * 1、生成延案申请流水号
     * 2、insert委外催收延案记录信息
     * 3、insert委外催收延案申请信息
     * 4、发起延案申请流程
     * 5、更新委外延案申请审批状态
     * 6、更新催收任务状态为"延案中"
     *
     * @param inColltDelayCaseRecordVo
     * @return
     */
    @RequestMapping(value = "/collt/delay/case/record", method = RequestMethod.POST)
    public @ResponseBody
    ResponseData<Integer> insertColltDelayCaseRecord(@RequestBody ColltDelayCaseRecordVO inColltDelayCaseRecordVo) {
        int outputVo = 0;
        setUserInfoToVO(inColltDelayCaseRecordVo);
        try {
            String delayCaseApply = getColltDelayCaseSerno();
            inColltDelayCaseRecordVo.setDelayCaseAppSerno(delayCaseApply);
            inColltDelayCaseRecordVo.setCreateUser(inColltDelayCaseRecordVo.getLoginUserId());
            inColltDelayCaseRecordVo.setCreateTime(TimeUtil.getCurrentDateTime());
            inColltDelayCaseRecordVo.setCreateUserOrg(inColltDelayCaseRecordVo.getLoginUserOrgCode());
            outputVo = colltDelayCaseRecordService.insertColltDelayCaseRecord(inColltDelayCaseRecordVo);

            if (outputVo > 0) {
                ColltDelayCaseAppVO colltDelayCaseAppVO = new ColltDelayCaseAppVO();
                setUserInfoToVO(colltDelayCaseAppVO);
                colltDelayCaseAppVO.setDelayCaseAppSerno(delayCaseApply);
                int num = insertColltDelayCaseAppVO(colltDelayCaseAppVO);
                if (num <= 0) {
                    throw new Exception("插入委外催收延案申请信息失败！");
                }
                ResponseData<Integer> result = submitColltDelayAppr(colltDelayCaseAppVO, outputVo);
                if (ApplicationConstance.SUCCESS.equals(result.getCode())) {
                    updColltTaskStsByPK(inColltDelayCaseRecordVo);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            outputVo = -1;
            return ResponseData.create(outputVo, ApplicationConstance.FAILURE, "发起委外催收延案申请审批流程失败!原因: " + e.getMessage(), false);
        }
        return getResponseData(outputVo);
    }


    @RequestMapping(value = "/collt/delay/case/upload", method = RequestMethod.POST)
    public void colltDelayCaseRecordUpload(HttpServletResponse respone, HttpServletRequest request) {
        ResponseData<Integer> result = new ResponseData<Integer>();
        List<File> files = new ArrayList<File>();
        respone.setContentType(CONTENTTYPE);
        OutputStream out = null;
        try {
            out = respone.getOutputStream();
            //获取文件
            files = flowCommonService.getFileList(request);
            if (!files.isEmpty()) {
                /**
                 * 将Excel文件解析成对应实体Bean
                 */
                List<ColltDelayCaseExcelVO> colltDelayCaseExcelVOList = ExcelImportRiskmUtil.importExcelByClass(files.get(0), ColltDelayCaseExcelVO.class, SHEETNAME);

                colltDelayCaseExcelVOList.remove(0);//去掉样例数据20201121lmj

                for (ColltDelayCaseExcelVO item : colltDelayCaseExcelVOList){
                    if("M".equals(item.getDelayTimeUnit())){
                        item.setDelayTimeUnit("002");
                    }
                }

                //检校数据
                String errMsg = checkDatas(colltDelayCaseExcelVOList);
                if (!StringUtil.isNullorBank(errMsg)){
                    throw new ExcelException(errMsg);
                }
                if (null != colltDelayCaseExcelVOList && !colltDelayCaseExcelVOList.isEmpty()) {
                    String cdcrSerno = this.getColltDelayCaseSerno();
                    int output = batchInsertVO(cdcrSerno, colltDelayCaseExcelVOList);
                    if (output < 1) {
                        new Exception("批量插入委外延案申请信息失败！");
                    }
                    ColltDelayCaseAppVO colltDelayCaseAppVO = new ColltDelayCaseAppVO();
                    setUserInfoToVO(colltDelayCaseAppVO);
                    colltDelayCaseAppVO.setDelayCaseAppSerno(cdcrSerno);
                    insertColltDelayCaseAppVO(colltDelayCaseAppVO);
                    // 发起流程
                    result = submitColltDelayAppr(colltDelayCaseAppVO, output);
                    if (ApplicationConstance.SUCCESS.equals(result.getCode())) {
                        // 批量更新催收任务信息表，任务状态为“"延案中"
                        updColltTaskStsByPk(colltDelayCaseExcelVOList, colltDelayCaseAppVO);
                    }
                } else {
                    throw new ExcelException("从文件获取数据为空!");
                }
            } else {
                throw new ExcelException("获取不到上传的文件！");
            }
        } catch (Exception e) {
            logger.error("文件上传失败,失败原因:", e);
            result = result.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
        } finally {
            String str = JSON.toJSONString(result);
            try {
                out.write(str.getBytes("UTF-8"));
                out.flush();
                out.close();
            } catch (IOException e) {
                logger.error("关闭数据流OutputStream出错，错误信息为：", e);
            }
        }
    }

    private String checkDatas(List<ColltDelayCaseExcelVO> colltResRecordExcelVOList) {
        String rs = "";
        ColltTaskInfoVO colltTaskInfoVO = new ColltTaskInfoVO();
        for (ColltDelayCaseExcelVO item : colltResRecordExcelVOList) {
            String colltTaskNo = item.getColltTaskNo();
            colltTaskInfoVO.setColltTaskNo(colltTaskNo);
            ColltTaskInfoVO query = colltTaskInfoService.queryByPk(colltTaskInfoVO);
            String msg = "催收任务编号[ " + colltTaskNo + " ]，";

            if (null == query){
                return msg + "导入数据不存在！";
            }
            if (!query.getColltBatchNo().equals(item.getColltBatchNo())){
                return msg + "导入数据分配批次号有误！";
            }
            if (!query.getOutsOrgCode().equals(item.getOutsOrgCode())){
                return msg + "导入数据委外机构编号有误！";
            }
            if (!query.getCusId().equals(item.getCusId())){
                return msg + "导入数据客户编号有误！";
            }
            if (!query.getLoanNo().equals(item.getLoanNo())){
                return msg + "导入数据借据编号有误！";
            }
            if (!query.getTaskSts().equals(item.getTaskSts())){
                return msg + "导入数据催收任务状态有误！";
            }
            rs = checkColltTaskSts(item.getTaskSts());
            if(StringUtil.isStrNotEmpty(rs)){
                return msg + rs;
            }
        }
        return rs;
    }

    /**
     * 校验催收任务状态
     * @param taskSts
     * @return
     */
    private String checkColltTaskSts(String taskSts){
        String result = "";
        if (!RiskColltConstant.COLLT_OUTS_TASK_STS_01.equals(taskSts) && !!RiskColltConstant.COLLT_OUTS_TASK_STS_02.equals(taskSts)
                && !RiskColltConstant.COLLT_OUTS_TASK_STS_07.equals(taskSts)){
            result = "现阶段只支持任务状态为'正常'，‘延案’，‘处理中’的催收任务进行延案申请！";
            return result;
        }
        return result;
    }



    private ResponseData<Integer> submitColltDelayAppr(ColltDelayCaseAppVO colltDelayCaseAppVO, int outputVo) {
        logger.info("发起委外催收延案申请流程开始，信息为:" + colltDelayCaseAppVO.toString());

        /**
         *  广银没有法人机构的概念，业务流转信息中的"业务流转标识"无法根据业务流转类型与法人机构号查询获取
         *  【目前解决方案】创建完业务流转，生成业务流转标识号，再拷贝到代码中（这个做法，完全符合现有的以开发人员为驱动的业务流转配置工具）
         * @date 2019/09/21
         */
        String flowId = "FW20190920000000014";
        String eventId = FlowConstance.COLLT_DALYA_CASE_APP_ENTER;
//        BizFlowInfoVO bizFlowInfoVO = new BizFlowInfoVO();
//        bizFlowInfoVO.setBizFlowType(FlowConstance.BIZ_FLOW_TYPE_10);
//        List<BizFlowInfoVO> listFlow = bizFlowInfoService.queryBizFlowInfoByFlowType(bizFlowInfoVO);
//        logger.info("查询到的业务流程参数为："+ JSONObject.toJSONString(listFlow));
//        if (Objects.nonNull(listFlow) && listFlow.size()>0) {
//            bizFlowInfoVO = listFlow.get(0);
//            // 得到业务流转ID
//            flowId = bizFlowInfoVO.getBizFlowId();
//        } else {
//            // 提交失败，不往委外延案申请表插入数据，需删除已插入委外催收延案记录表的数据
//            colltDelayCaseRecordService.deleteByDelayCaseAppSerno(colltDelayCaseAppVO.getDelayCaseAppSerno());
//            outputVo = -1;
//            return setRespMsgFail(outputVo, "未配置流程相关信息，提交失败!");
//        }
        EngineHttpRequestVO eVo = new EngineHttpRequestVO();
        eVo.setBizLagelOrgCode(colltDelayCaseAppVO.getLoginUserOrgCode());
        eVo.setE_bizSerno(colltDelayCaseAppVO.getDelayCaseAppSerno());
        eVo.setFlowId(flowId);
        //业务事件标识
        eVo.setEventId(eventId);
        eVo.setG_bizSerno(colltDelayCaseAppVO.getDelayCaseAppSerno());
        eVo.setBizLagelOrgCode(colltDelayCaseAppVO.getLoginUserOrgCode());
        eVo.setData(colltDelayCaseAppVO);
        try {
            //判断流程配置岗位是否有效
            if (!flowCommonService.dutyFlowCheck(eventId, flowId)){
                throw new Exception("发起委外催收延案申请流程失败!原因: 流程岗位已失效");
            }
            HttpClientUtil.callFlowEngine(flowUrlConfigService.getRestfulSyncStartEventUrl(), eVo, String.class);
            updColltDelayCaseAppVO(colltDelayCaseAppVO);
        } catch (Exception e) {
            colltDelayCaseRecordService.deleteByDelayCaseAppSerno(colltDelayCaseAppVO.getDelayCaseAppSerno());
            logger.error(e.getMessage());
            outputVo = -1;
            return ResponseData.create(outputVo, ApplicationConstance.FAILURE, "发起委外催收延案申请审批流程失败!原因: " + e.getMessage(), false);
        }
        return getResponseData(1);
    }

    /**
     * 将数据插入委外催收延案申请表
     * @param insertVO
     * @return
     */
    private int insertColltDelayCaseAppVO(ColltDelayCaseAppVO insertVO){
        // 设置申请日期为营业日期
        insertVO.setApplyDate(pubSysInfoService.getOpenday(BaseConstant.SYS_ID_1001));
        //insertVO.setOpUserCode(insertVO.getLoginUserId());
        //insertVO.setOpOrgCode(insertVO.getLoginUserOrgCode());
        insertVO.setApproveStatus(ConsoleConstant.APRV_STATUS_01);
        insertVO.setCreateUser(insertVO.getLoginUserId());
        insertVO.setCreateTime(TimeUtil.getCurrentDateTime());
        insertVO.setCreateUserOrg(insertVO.getLoginUserOrgCode());
        insertVO.setLastChgUsr(insertVO.getLoginUserId());
        return  colltDelayCaseAppService.insertColltDelayCaseApp(insertVO);
    }

    /**
     * 更新委外催收延案申请审批状态为"审批中"
     * @param colltDelayCaseAppVO
     */
    private void updColltDelayCaseAppVO(ColltDelayCaseAppVO colltDelayCaseAppVO) {
        colltDelayCaseAppVO.setApproveStatus(ConsoleConstant.APRV_STATUS_02);
        colltDelayCaseAppVO.setLastChgUsr(colltDelayCaseAppVO.getLoginUserId());
        colltDelayCaseAppService.updateByPk(colltDelayCaseAppVO);
    }

    /**
     * 批量更新催收任务信息的任务状态为"延案中"
     * @param cdcExcelVoList
     * @param colltDelayCaseAppVO
     */
    private void updColltTaskStsByPk(List<ColltDelayCaseExcelVO> cdcExcelVoList, ColltDelayCaseAppVO colltDelayCaseAppVO) {
        List<ColltTaskInfoVO> updColltTaskList = new ArrayList<>();
        cdcExcelVoList.forEach(excelVO -> {
            ColltTaskInfoVO colltTaskInfoVO = new ColltTaskInfoVO();
            colltTaskInfoVO.setColltTaskNo(excelVO.getColltTaskNo());
            colltTaskInfoVO.setTaskSts(RiskColltConstant.COLLT_OUTS_TASK_STS_06);
            colltTaskInfoVO.setLastUpdateUser(colltDelayCaseAppVO.getLoginUserId());
            updColltTaskList.add(colltTaskInfoVO);
        });
        colltTaskInfoService.batchUpdateVO(updColltTaskList);
    }

    /**
     *
     * @param colltDelayCaseRecordVO
     */
    private void updColltTaskStsByPK(ColltDelayCaseRecordVO colltDelayCaseRecordVO) {
        ColltTaskInfoVO colltTaskInfoVO = new ColltTaskInfoVO();
        String colltTaskNo = colltDelayCaseRecordVO.getColltTaskNo();
        colltTaskInfoVO.setColltTaskNo(colltTaskNo);
        colltTaskInfoVO.setTaskSts(RiskColltConstant.COLLT_OUTS_TASK_STS_06);
        colltTaskInfoVO.setLastUpdateUser(colltDelayCaseRecordVO.getLoginUserId());
        int num = colltTaskInfoService.updateByPk(colltTaskInfoVO);
        if (num != 1) {
            logger.error("根据催收任务编号:" + colltTaskNo + "，更新任务状态为延案中失败！");
        }
    }

    public String getColltDelayCaseSerno() throws ExcelException {
        String result = null;
        try {
            result = sequenceService.getSequence("DELAY_CASE_APP_SERNO", null, null);
        } catch (Exception e) {
            throw new ExcelException("生成延案申请流水号出错，错误信息为：" + e.getMessage());
        }
        return result;
    }

    /**
     * 批量插入委外催收延案记录表
     * @param serno
     * @param colltDelayCaseExcelVOS
     * @return
     */
    public int batchInsertVO(String serno, List<ColltDelayCaseExcelVO> colltDelayCaseExcelVOS) {
        List<ColltDelayCaseRecordVO> batchInsertList = new ArrayList<>();
        String orgCode = this.getUserInfo().getOrgInfo().getOrgCode();
        String userCode = this.getUserInfo().getUserId();
        String createTime = TimeUtil.getCurrentDateTime();
        for (ColltDelayCaseExcelVO cdceVo : colltDelayCaseExcelVOS) {
            ColltDelayCaseRecordVO colltDelayCaseRecordVO = new ColltDelayCaseRecordVO();
            colltDelayCaseRecordVO.setColltTaskNo(cdceVo.getColltTaskNo());
            colltDelayCaseRecordVO.setColltBatchNo(cdceVo.getColltBatchNo());
            colltDelayCaseRecordVO.setDelayCaseAppSerno(serno);
            colltDelayCaseRecordVO.setOutsOrgCode(cdceVo.getOutsOrgCode());
            colltDelayCaseRecordVO.setOutsOrgName(cdceVo.getOutsOrgName());
            colltDelayCaseRecordVO.setTaskSts(cdceVo.getTaskSts());
            colltDelayCaseRecordVO.setCusId(cdceVo.getCusId());
            colltDelayCaseRecordVO.setCusName(cdceVo.getCusName());
            colltDelayCaseRecordVO.setLoanNo(cdceVo.getLoanNo());
            if(StringUtil.isNullorBank(cdceVo.getDelayTime())){
                //延案时间不填写，则默认1个月
                colltDelayCaseRecordVO.setDelayTime("1");
                colltDelayCaseRecordVO.setDelayTimeUnit(RiskColltConstant.TIME_UNIT_002);
            }else{
                colltDelayCaseRecordVO.setDelayTime(cdceVo.getDelayTime());
                colltDelayCaseRecordVO.setDelayTimeUnit(cdceVo.getDelayTimeUnit());
            }
            colltDelayCaseRecordVO.setOpUserCode(cdceVo.getOpUserCode());
            colltDelayCaseRecordVO.setOpOrgCode(cdceVo.getOpOrgCode());
            colltDelayCaseRecordVO.setCreateUser(userCode);
            colltDelayCaseRecordVO.setCreateTime(createTime);
            colltDelayCaseRecordVO.setCreateUserOrg(orgCode);

            batchInsertList.add(colltDelayCaseRecordVO);
        }

        return colltDelayCaseRecordService.insertVoBatch(batchInsertList);
    }


}
